home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / oleofile.c < prev    next >
C/C++ Source or Header  |  1993-03-30  |  19KB  |  940 lines

  1. /*    Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17. /* this file was derived from the file sylk.c */
  18. #include "funcdef.h"
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include "sysdef.h"
  22. #include "io-generic.h"
  23. #include "io-abstract.h"
  24. #include "io-utils.h"
  25. #include "io-term.h"
  26. #include "font.h"
  27. #include "global.h"
  28. #include "cell.h"
  29. #include "line.h"
  30. #include "sylk.h"
  31. #include "lists.h"
  32. #include "ref.h"
  33. #include "regions.h"
  34. #include "window.h"
  35. #include "info.h"
  36. #include "cmd.h"
  37.  
  38.  
  39. /* These functions read and write OLEO style files. */
  40.  
  41. void
  42. oleo_read_file (fp, ismerge)
  43.      FILE *fp;
  44.      int ismerge;
  45. {
  46.   char *ptr;
  47.   CELLREF crow = 0, ccol = 0, czrow = 0, czcol = 0;
  48.   int lineno;
  49.   char cbuf[1024];
  50.   char expbuf[1024];
  51.   char *vname, *vval;
  52.   int vlen = 0;
  53.   int cprot;
  54.   char *cexp, *cval;
  55.   CELL *cp;
  56.   struct rng rng;
  57.   int fmt = 0;
  58.   int jst = 0;
  59.   struct font_memo * fnt = 0;
  60.   struct font_memo ** fnt_map = 0;
  61.   int fnt_map_size = 0;
  62.   int fnt_map_alloc = 0;
  63.   int font_spec_in_format = 1;    /* Reset if we discover this is a v1.1 file. */
  64.   
  65.   long mx_row = MAX_ROW, mx_col = MAX_COL;
  66.   int old_a0;
  67.   int next_a0;
  68.  
  69.   old_a0 = a0;
  70.   next_a0 = old_a0;
  71.   a0 = 0;
  72.   lineno = 0;
  73.   if (!ismerge)
  74.     clear_spreadsheet ();
  75.   while (fgets (cbuf, sizeof (cbuf), fp))
  76.     {
  77.       lineno++;
  78.       if (lineno % 50 == 0)
  79.     io_info_msg ("Line %d", lineno);
  80.       if (ptr = (char *)index (cbuf, '\n'))
  81.     *ptr = '\0';
  82.  
  83.       ptr = cbuf;
  84.       switch (*ptr)
  85.     {
  86.     case '#':        /* comment line -- ignored */
  87.       break;
  88.     case '%':        /* Font or pixel size data. */
  89.       ptr++;
  90.       switch (*ptr)
  91.         {
  92.         case 'F':        /* %F font-name */
  93.           if (fnt_map_size == fnt_map_alloc)
  94.         {
  95.           fnt_map_alloc = (fnt_map_alloc + 1) * 2;
  96.           fnt_map =
  97.             ((struct font_memo **)
  98.              ck_remalloc
  99.              (fnt_map, fnt_map_alloc * sizeof (struct font_memo *)));
  100.         }
  101.           fnt_map[fnt_map_size++] = parsed_matching_font (ptr + 1);
  102.           break;
  103.         case 'f':        /* %f range font-name */
  104.           {
  105.         struct rng rng;
  106.         /* This field only occurs in files written by 1.1
  107.          * oleo.  It's presense indicates that when parsing
  108.          * format fields, we should *not* reset cell fonts to 0.
  109.          */
  110.         font_spec_in_format = 0;
  111.         ++ptr;
  112.         while (isspace (*ptr))
  113.           ++ptr;
  114.         if (!parse_cell_or_range (&ptr, &rng))
  115.           goto bad_field;
  116.         while (isspace (*ptr))
  117.           ++ptr;
  118.         {
  119.           struct font_memo * fm = parsed_matching_font (ptr);
  120.           set_region_font (&rng, fm->names->oleo_name, fm->scale);
  121.         }
  122.         break;
  123.           }
  124.         default:
  125.           goto bad_field;
  126.         }
  127.       break;
  128.     case 'F':        /* Format field */
  129.       vlen = 0;
  130.       ptr++;
  131.       fnt = 0;    /* The font must be explicitly overriden for a cell. */
  132.       while (*ptr)
  133.         {
  134.           if (*ptr != ';')
  135.         goto bad_field;
  136.           ptr++;
  137.           switch (*ptr++)
  138.         {
  139.           int clo, chi, cwid;
  140.         case 'C':    /* Column from rows 1 to 255 */
  141.           czcol = astol (&ptr);
  142.           vlen = 2;
  143.           break;
  144.  
  145.         case 'D':    /* Default format */
  146.           switch (*ptr++)
  147.             {
  148.             case 'G':
  149.               default_fmt = FMT_GEN - PRC_FLT;
  150.               break;
  151.             case 'E':
  152.               default_fmt = FMT_EXP - PRC_FLT;
  153.               break;
  154.             case 'F':
  155.               default_fmt = FMT_FXT - PRC_FLT;
  156.               break;
  157.             case '$':
  158.               default_fmt = FMT_DOL - PRC_FLT;
  159.               break;
  160.             case '*':    /* * format implemented as +- format */
  161.               default_fmt = FMT_GPH;
  162.               break;
  163.             case ',':    /* JF */
  164.               default_fmt = FMT_CMA - PRC_FLT;
  165.               break;
  166.             case 'U':
  167.               default_fmt = FMT_USR - PRC_FLT;
  168.               break;
  169.             case '%':
  170.               default_fmt = FMT_PCT - PRC_FLT;
  171.               break;
  172.             case 'H':
  173.               default_fmt = FMT_HID;
  174.               break;
  175.               /* End of JF */
  176.             default:
  177.               io_error_msg ("Line %d: format %c not supported", lineno, ptr[-1]);
  178.               break;
  179.             }
  180.           if (*ptr == 'F')
  181.             {
  182.               default_fmt += PRC_FLT;
  183.               ptr++;
  184.             }
  185.           else
  186.             default_fmt += astol (&ptr);
  187.           switch (*ptr++)
  188.             {
  189.             case 'C':
  190.               default_jst = JST_CNT;
  191.               break;
  192.             case 'L':
  193.               default_jst = JST_LFT;
  194.               break;
  195.             case 'R':
  196.               default_jst = JST_RGT;
  197.               break;
  198.             case 'G':    /* General format not supported */
  199.             default:
  200.               io_error_msg ("Line %d: Alignment %c not supported", lineno, ptr[-1]);
  201.               break;
  202.             }
  203.           default_width = astol (&ptr);
  204.           break;
  205.  
  206.         case 'f': /* Font specification */
  207.           {
  208.             int id;
  209.             id = astol(&ptr);
  210.             if (id < 0 || id >= fnt_map_size)
  211.               {
  212.             io_error_msg ("Line %d: Undefined font (%d)\n",
  213.                       lineno, id);
  214.             break;
  215.               }
  216.             fnt = fnt_map[id];
  217.             break;
  218.           }
  219.  
  220.         case 'F':
  221.           switch (*ptr++)
  222.             {
  223.             case 'D':
  224.               fmt = FMT_DEF;
  225.               break;
  226.             case 'G':
  227.               fmt = FMT_GEN - PRC_FLT;
  228.               break;
  229.             case 'E':
  230.               fmt = FMT_EXP - PRC_FLT;
  231.               break;
  232.             case 'F':
  233.               fmt = FMT_FXT - PRC_FLT;
  234.               break;
  235.             case '$':
  236.               fmt = FMT_DOL - PRC_FLT;
  237.               break;
  238.             case '*':    /* JF implemented as +- format */
  239.               fmt = FMT_GPH;
  240.               break;
  241.             case ',':    /* JF */
  242.               fmt = FMT_CMA - PRC_FLT;
  243.               break;
  244.             case 'U':
  245.               fmt = FMT_USR - PRC_FLT;
  246.               break;
  247.             case '%':
  248.               fmt = FMT_PCT - PRC_FLT;
  249.               break;
  250.             case 'H':
  251.               fmt = FMT_HID;
  252.               break;    /* END of JF */
  253.             case 'C':
  254.             default:
  255.               io_error_msg ("Line %d: format %c not supported", lineno, ptr[-1]);
  256.               fmt = FMT_DEF;
  257.               break;
  258.             }
  259.           if (*ptr == 'F')
  260.             {
  261.               fmt += PRC_FLT;
  262.               ptr++;
  263.             }
  264.           else
  265.             fmt += astol (&ptr);
  266.           switch (*ptr++)
  267.             {
  268.             case 'C':
  269.               jst = JST_CNT;
  270.               break;
  271.             case 'L':
  272.               jst = JST_LFT;
  273.               break;
  274.             case 'R':
  275.               jst = JST_RGT;
  276.               break;
  277.             case 'D':
  278.               jst = JST_DEF;
  279.               break;
  280.             default:
  281.               io_error_msg ("Line %d: Alignment %c not supported", lineno, ptr[-1]);
  282.               jst = JST_DEF;
  283.               break;
  284.             }
  285.           vlen = 1;
  286.           break;
  287.         case 'R':    /* Row from cols 1 to 63 */
  288.           czrow = astol (&ptr);
  289.           vlen = 4;
  290.           break;
  291.  
  292.         case 'W':    /* Width of clo to chi is cwid */
  293.           clo = astol (&ptr);
  294.           chi = astol (&ptr);
  295.           cwid = astol (&ptr) + 1;
  296.           for (; clo <= chi; clo++)
  297.             set_width (clo, cwid);
  298.           break;
  299.  
  300.         case 'H':    /* JF: extension */
  301.           clo = astol (&ptr);
  302.           chi = astol (&ptr);
  303.           cwid = astol (&ptr) + 1;
  304.           for (; clo <= chi; clo++)
  305.             set_height (clo, cwid);
  306.           break;
  307.         case 'c':
  308.           ccol = astol (&ptr);
  309.           break;
  310.         case 'r':
  311.           crow = astol (&ptr);
  312.           break;
  313.  
  314.         default:
  315.           goto bad_field;
  316.         }
  317.         }
  318.       switch (vlen)
  319.         {
  320.         case 1:
  321.           cp = find_or_make_cell (crow, ccol);
  322.           SET_FMT (cp, fmt);
  323.           SET_JST (cp, jst);
  324.           if (font_spec_in_format)
  325.         cp->cell_font = fnt;
  326.           break;
  327.         case 2:
  328.           rng.lr = MIN_ROW;
  329.           rng.lc = czcol;
  330.           rng.hr = mx_row;
  331.           rng.hc = czcol;
  332.           make_cells_in_range (&rng);
  333.           while (cp = next_cell_in_range ())
  334.         {
  335.           SET_FMT (cp, fmt);
  336.           SET_JST (cp, jst);
  337.           if (font_spec_in_format)
  338.             cp->cell_font = fnt;
  339.         }
  340.           break;
  341.         case 4:
  342.           rng.lr = czrow;
  343.           rng.lc = MIN_COL;
  344.           rng.hr = czrow;
  345.           rng.hc = mx_col;
  346.           make_cells_in_range (&rng);
  347.           while (cp = next_cell_in_range ())
  348.         {
  349.           SET_FMT (cp, fmt);
  350.           SET_JST (cp, jst);
  351.           if (font_spec_in_format)
  352.             cp->cell_font = fnt;
  353.         }
  354.           break;
  355.         default:
  356.           break;
  357.         }
  358.       break;
  359.  
  360.     case 'B':        /* Boundry field, ignored */
  361.       ptr++;
  362.       while (*ptr)
  363.         {
  364.           if (*ptr != ';')
  365.         goto bad_field;
  366.           ptr++;
  367.           switch (*ptr++)
  368.         {
  369.         case 'c':
  370.           mx_col = astol (&ptr);
  371.           if (mx_col > MAX_COL)
  372.             {
  373.               io_error_msg ("Boundry column %lu too large!", mx_col);
  374.               mx_col = MAX_COL;
  375.             }
  376.           break;
  377.         case 'r':
  378.           mx_row = astol (&ptr);
  379.           if (mx_row > MAX_ROW)
  380.             {
  381.               io_error_msg ("Boundry row %lu too large!", mx_row);
  382.               mx_row = MAX_ROW;
  383.             }
  384.           break;
  385.         default:
  386.           goto bad_field;
  387.         }
  388.         }
  389.       break;
  390.  
  391.     case 'N':        /* A Name field */
  392.       if (ptr[1] != 'N')
  393.         goto bad_field;
  394.       ptr += 2;
  395.       vname = 0;
  396.       vval = 0;
  397.       while (*ptr)
  398.         {
  399.           if (*ptr != ';')
  400.         goto bad_field;
  401.           *ptr++ = '\0';
  402.           switch (*ptr++)
  403.         {
  404.         case 'N':    /* Name is */
  405.           vname = ptr;
  406.           while (*ptr && *ptr != ';')
  407.             ptr++;
  408.           vlen = ptr - vname;
  409.           break;
  410.         case 'E':    /* Expression is */
  411.           vval = ptr;
  412.           while (*ptr && *ptr != ';')
  413.             ptr++;
  414.           break;
  415.         default:
  416.           --ptr;
  417.           goto bad_field;
  418.         }
  419.         }
  420.       if (!vname || !vval)
  421.         goto bad_field;
  422.       *ptr = '\0';
  423.       ptr = new_var_value (vname, vlen, vval);
  424.       if (ptr)
  425.         io_error_msg ("Line %d: Couldn't set %.*s to %s: %s", lineno, vlen, vname, vval, ptr);
  426.       break;
  427.  
  428.     case 'C':        /* A Cell entry */
  429.       cprot = 0;
  430.       cval = 0;
  431.       cexp = 0;
  432.       cval = 0;
  433.       ptr++;
  434.       while (*ptr)
  435.         {
  436.           int quotes;
  437.  
  438.           if (*ptr != ';')
  439.         goto bad_field;
  440.           *ptr++ = '\0';
  441.           switch (*ptr++)
  442.         {
  443.         case 'c':
  444.           ccol = astol (&ptr);
  445.           break;
  446.         case 'r':
  447.           crow = astol (&ptr);
  448.           break;
  449.         case 'R':
  450.           czrow = astol (&ptr);
  451.           break;
  452.         case 'C':
  453.           czcol = astol (&ptr);
  454.           break;
  455.         case 'P':    /* This cell is Protected */
  456.           cprot++;
  457.           break;
  458.         case 'K':    /* This cell's Konstant value */
  459.           cval = ptr;
  460.           quotes = 0;
  461.           while (*ptr && (*ptr != ';' || quotes > 0))
  462.             if (*ptr++ == '"')
  463.               quotes = !quotes;
  464.           break;
  465.         case 'E':    /* This cell's Expression */
  466.           cexp = ptr;
  467.           quotes = 0;
  468.           while (*ptr && (*ptr != ';' || quotes > 0))
  469.             if (*ptr++ == '"')
  470.               quotes = !quotes;
  471.  
  472.           break;
  473.         case 'G':
  474.           strcpy (expbuf, cval);
  475.           break;
  476.         case 'D':
  477.           strcpy (expbuf, cexp);
  478.           break;
  479.         case 'S':
  480.           cexp = expbuf;
  481.           break;
  482.         default:
  483.           --ptr;
  484.           goto bad_field;
  485.         }
  486.         }
  487.       *ptr = '\0';
  488.       if (cexp && cval && strcmp (cexp, cval))
  489.         {
  490.           ptr = read_new_value (crow, ccol, cexp, cval);
  491.           if (ptr)
  492.         {
  493.           io_error_msg ("Line %d: %d,%d: Read '%s' %s", lineno, crow, ccol, cexp, ptr);
  494.           break;
  495.         }
  496.         }
  497.       else if (cval)
  498.         {
  499.           ptr = read_new_value (crow, ccol, 0, cval);
  500.           if (ptr)
  501.         {
  502.           io_error_msg ("Line %d: %d,%d: Val '%s' %s", lineno, crow, ccol, cexp, ptr);
  503.           break;
  504.         }
  505.         }
  506.       else if (cexp)
  507.         {
  508.           ptr = read_new_value (crow, ccol, cexp, 0);
  509.           if (ptr)
  510.         {
  511.           io_error_msg ("Line %d: %d,%d: Exp '%s' %s", lineno, crow, ccol, cexp, ptr);
  512.           break;
  513.         }
  514.         }
  515.       if (cprot)
  516.         SET_LCK (find_or_make_cell (crow, ccol), LCK_LCK);
  517.       if (ismerge)
  518.         push_cell (crow, ccol);
  519.       /* ... */
  520.       break;
  521.     case 'E':
  522.       break;
  523.     case 'W':
  524.       io_read_window_config (ptr + 2);
  525.       break;
  526.     case 'U':
  527.       /* JF extension:  read user-defined formats */
  528.       read_mp_usr_fmt (ptr + 1);
  529.       break;
  530.       /* JF extension: read uset-settable options */
  531.     case 'O':
  532.       a0 = next_a0;
  533.       read_mp_options (ptr + 2);
  534.       next_a0 = a0;
  535.       a0 = 0;
  536.       break;
  537.     default:
  538.     bad_field:
  539.       a0 = old_a0;
  540.       if (!ismerge)
  541.         clear_spreadsheet ();
  542.       io_recenter_all_win ();
  543.       io_error_msg ("Line %d: Unknown OLEO line \"%s\"", lineno, cbuf);
  544.       return;
  545.     }
  546.     }
  547.   if (!feof (fp))
  548.     {
  549.       if (!ismerge)
  550.     clear_spreadsheet ();
  551.       io_recenter_all_win ();
  552.       io_error_msg ("read-file: read-error near line %d.", lineno);
  553.       return;
  554.     }
  555.   a0 = next_a0;
  556.   io_recenter_all_win ();
  557. }
  558.  
  559. static char *
  560. oleo_fmt_to_str (f1)
  561.      int f1;
  562. {
  563.   static char p_buf[40];
  564.   int p1;
  565.  
  566.   p_buf[1] = '\0';
  567.   switch (f1)
  568.     {
  569.     case FMT_DEF:
  570.       p_buf[0] = 'D';
  571.       break;
  572.     case FMT_HID:
  573.       p_buf[0] = 'H';
  574.       break;
  575.     case FMT_GPH:
  576.       p_buf[0] = '*';
  577.       break;
  578.     default:
  579.       p1 = GET_PRC (f1);
  580.       if (p1 == PRC_FLT)
  581.     {
  582.       p_buf[1] = 'F';
  583.       p_buf[2] = '\0';
  584.     }
  585.       else
  586.     sprintf (&p_buf[1], "%d", p1);
  587.       switch (f1 | PRC_FLT)
  588.     {
  589.     case FMT_USR:
  590.       p_buf[0] = 'U';
  591.       break;
  592.     case FMT_GEN:
  593.       p_buf[0] = 'G';
  594.       break;
  595.     case FMT_DOL:
  596.       p_buf[0] = '$';
  597.       break;
  598.     case FMT_PCT:
  599.       p_buf[0] = '%';
  600.       break;
  601.     case FMT_FXT:
  602.       p_buf[0] = 'F';
  603.       break;
  604.     case FMT_CMA:
  605.       p_buf[0] = ',';
  606.       break;
  607.     case FMT_EXP:
  608.       p_buf[0] = 'E';
  609.       break;
  610.     default:
  611.       p_buf[0] = '?';
  612.       break;
  613.     }
  614.       break;
  615.     }
  616.   return p_buf;
  617. }
  618.  
  619. static char
  620. jst_to_chr (just)
  621.      int just;
  622. {
  623.   switch (just)
  624.     {
  625.     case JST_DEF:
  626.       return 'D';
  627.     case JST_LFT:
  628.       return 'L';
  629.     case JST_RGT:
  630.       return 'R';
  631.     case JST_CNT:
  632.       return 'C';
  633.     default:
  634.       return '?';
  635.     }
  636. }
  637.  
  638. static FILE *oleo_fp;
  639. static struct rng *oleo_rng;
  640.  
  641. static void 
  642. oleo_write_var (name, var)
  643.      char *name;
  644.      struct var *var;
  645. {
  646.   if (var->var_flags
  647.       == VAR_UNDEF && (!var->var_ref_fm || var->var_ref_fm->refs_used == 0))
  648.     return;
  649.   switch (var->var_flags)
  650.     {
  651.     case VAR_UNDEF:
  652.       break;
  653.     case VAR_CELL:
  654.       if (var->v_rng.lr >= oleo_rng->lr && var->v_rng.lr <= oleo_rng->hr && var->v_rng.lc >= oleo_rng->lc && var->v_rng.lc <= oleo_rng->hc)
  655.     (void) fprintf (oleo_fp, "NN;N%s;E%s\n", var->var_name, cell_name (var->v_rng.lr, var->v_rng.lc));
  656.       break;
  657.     case VAR_RANGE:
  658.       if (var->v_rng.lr < oleo_rng->lr || var->v_rng.hr > oleo_rng->hr || var->v_rng.lc < oleo_rng->lc || var->v_rng.hc > oleo_rng->hc)
  659.     break;
  660.  
  661.       (void) fprintf (oleo_fp, "NN;N%s;E%s\n", var->var_name, range_name (&(var->v_rng)));
  662.       break;
  663. #ifdef TEST
  664.     default:
  665.       panic ("Unknown var type %d", var->var_flags);
  666. #endif
  667.     }
  668. }
  669.  
  670. static void
  671. write_mp_windows (fp)
  672.      FILE *fp;
  673. {
  674.   struct line line;
  675.   line.alloc = 0;
  676.   line.buf = 0;
  677.   io_write_window_config (&line);
  678.   fputs (line.buf, fp);
  679.   free (line.buf);
  680. }
  681.  
  682. void
  683. oleo_write_file (fp, rng)
  684.      FILE *fp;
  685.      struct rng *rng;
  686. {
  687.   CELLREF r, c;
  688.   CELL *cp;
  689.   CELLREF crow = 0, ccol = 0;
  690.   unsigned short w;
  691.   /* struct var *var; */
  692.   int old_a0;
  693.   int fnt_map_size = 0;
  694.  
  695.   (void) fprintf (fp, "# This file was created by GNU Oleo\n");
  696.  
  697.   /* All versions of the oleo file format should have a 
  698.    * version cookie on the second line.
  699.    */
  700.   (void) fprintf (fp, "# format 1.0\n");
  701.  
  702.   /* If no range given, write the entire file */
  703.   if (!rng)
  704.     {
  705.       int n;
  706.       int fmts;
  707.       char *data[9];
  708.  
  709.       rng = &all_rng;
  710.  
  711.       (void) fprintf (fp, "F;D%s%c%u\n", oleo_fmt_to_str (default_fmt), jst_to_chr (default_jst), default_width);
  712.  
  713.       fmts = usr_set_fmts ();
  714.       for (n = 0; n < 16; n++)
  715.     {
  716.       if (fmts & (1 << n))
  717.         {
  718.           get_usr_stats (n, data);
  719.           fprintf (fp, "U;N%u;P%s;S%s", n + 1, data[7], data[8]);
  720.           if (data[0][0])
  721.         fprintf (fp, ";HP%s", data[0]);
  722.           if (data[1][0])
  723.         fprintf (fp, ";HN%s", data[1]);
  724.           if (data[2][0])
  725.         fprintf (fp, ";TP%s", data[2]);
  726.           if (data[3][0])
  727.         fprintf (fp, ";TN%s", data[3]);
  728.           if (data[4][0])
  729.         fprintf (fp, ";Z%s", data[4]);
  730.           if (data[5][0])
  731.         fprintf (fp, ";C%s", data[5]);
  732.           if (data[6])
  733.         fprintf (fp, ";D%s", data[6]);
  734.           putc ('\n', fp);
  735.         }
  736.     }
  737.       write_mp_options (fp);
  738.     }
  739.  
  740.   old_a0 = a0;
  741.   a0 = 0;
  742.  
  743.   find_widths (rng->lc, rng->hc);
  744.   w = next_width (&c);
  745.   while (w)
  746.     {
  747.       CELLREF cc, ccc;
  748.       unsigned short ww;
  749.       cc = c;
  750.       do
  751.     ww = next_width (&ccc);
  752.       while (ccc == ++cc && ww == w);
  753.       (void) fprintf (fp, "F;W%u %u %u\n", c, cc - 1, w - 1);
  754.       c = ccc;
  755.       w = ww;
  756.     }
  757.  
  758.   find_heights (rng->lr, rng->hr);
  759.   w = next_height (&r);
  760.   while (w)
  761.     {
  762.       CELLREF rr, rrr;
  763.       unsigned short ww;
  764.  
  765.       rr = r;
  766.       do
  767.     ww = next_height (&rrr);
  768.       while (rrr == ++rr && ww == w);
  769.       (void) fprintf (fp, "F;H%u %u %u\n", r, rr - 1, w - 1);
  770.       r = rrr;
  771.       w = ww;
  772.     }
  773.  
  774.   oleo_fp = fp;
  775.   oleo_rng = rng;
  776.   for_all_vars (oleo_write_var);
  777.   find_cells_in_range (rng);
  778.  
  779.   {
  780.     struct font_memo * fm;
  781.     for (fm = font_list; fm; fm = fm->next)
  782.       fm->id_memo = -1;
  783.   }
  784.   while (cp = next_row_col_in_range (&r, &c))
  785.     {
  786.       char *ptr;
  787.       int f1, j1;
  788.       char p_buf[40];
  789.  
  790.       f1 = GET_FMT (cp);
  791.       j1 = GET_JST (cp);
  792.       if (f1 != FMT_DEF || j1 != JST_DEF || cp->cell_font)
  793.     {
  794.       if (cp->cell_font)
  795.         {
  796.           if (cp->cell_font->id_memo < 0)
  797.         {
  798.           cp->cell_font->id_memo = fnt_map_size++;
  799.           fprintf (fp, "%%F%s,%s,%f\n",
  800.                cp->cell_font->names->x_name,
  801.                cp->cell_font->names->ps_name,
  802.                cp->cell_font->scale);
  803.         }
  804.         }
  805.       (void) fprintf (fp, "F;");
  806.       if (c != ccol)
  807.         {
  808.           (void) fprintf (fp, "c%u;", c);
  809.           ccol = c;
  810.         }
  811.       if (r != crow)
  812.         {
  813.           (void) fprintf (fp, "r%u;", r);
  814.           crow = r;
  815.         }
  816.       if (cp->cell_font)
  817.         (void) fprintf (fp, "f%d;", cp->cell_font->id_memo);
  818.       (void) fprintf (fp, "F%s%c\n",
  819.               oleo_fmt_to_str (f1), jst_to_chr (j1));
  820.     }
  821.  
  822.       if (!GET_TYP (cp) && !cp->cell_formula)
  823.     continue;
  824.  
  825.       (void) fprintf (fp, "C;");
  826.       if (c != ccol)
  827.     {
  828.       (void) fprintf (fp, "c%u;", c);
  829.       ccol = c;
  830.     }
  831.       if (r != crow)
  832.     {
  833.       (void) fprintf (fp, "r%u;", r);
  834.       crow = r;
  835.     }
  836.  
  837.       if (cp->cell_formula)
  838.     {
  839.       (void) fprintf (fp, "E%s", decomp (r, c, cp));
  840.       decomp_free ();
  841.     }
  842.  
  843.       switch (GET_TYP (cp))
  844.     {
  845.     case 0:
  846.       ptr = 0;
  847.       break;
  848.     case TYP_STR:
  849.       ptr = 0;
  850.       if (cp->cell_formula)
  851.         putc (';', fp);
  852.       (void) fprintf (fp, "K\"%s\"", cp->cell_str);
  853.       break;
  854.     case TYP_FLT:
  855.       ptr = flt_to_str (cp->cell_flt);
  856.       break;
  857.     case TYP_INT:
  858.       sprintf (p_buf, "%ld", cp->cell_int);
  859.       ptr = p_buf;
  860.       break;
  861.     case TYP_BOL:
  862.       ptr = bname[cp->cell_bol];
  863.       break;
  864.     case TYP_ERR:
  865.       ptr = ename[cp->cell_err];
  866.       break;
  867.     default:
  868.       ptr = 0;
  869. #ifdef TEST
  870.       panic ("What cell type %d", GET_TYP (cp));
  871. #endif
  872.     }
  873.  
  874.       if (ptr)
  875.     {
  876.       if (cp->cell_formula)
  877.         putc (';', fp);
  878.       (void) fprintf (fp, "K%s", ptr);
  879.     }
  880.       if (GET_LCK (cp) == LCK_LCK)
  881.     (void) fprintf (fp, ";P");
  882.  
  883.       putc ('\n', fp);
  884.     }
  885.  
  886.   if (rng == &all_rng)
  887.     write_mp_windows (fp);
  888.  
  889.   (void) fprintf (fp, "E\n");
  890.   a0 = old_a0;
  891. }
  892.  
  893. int
  894. oleo_set_options
  895.   (set_opt, option)
  896.      int set_opt;
  897.      char *option;
  898. {
  899.   return -1;
  900. }
  901.  
  902. void
  903. oleo_show_options ()
  904. {
  905.   io_text_line ("File format: oleo.");
  906. }
  907.  
  908.  
  909. #if 0
  910. This was used in releases 1.0 and 1.1 to write fonts.  
  911. It is no longer used but is kept here for reference since 1.2 and later
  912. versions should continue to understand the older file format for a while.
  913.  
  914. static int
  915. oleo_write_fonts (rng, font, ignore)
  916.      struct rng *rng;
  917.      struct font_memo *font;
  918.      void *ignore;
  919. {
  920.   struct rng r;
  921.   char *rname;
  922.   r = *rng;
  923.   if (r.lr < oleo_rng->lr)
  924.     r.lr = oleo_rng->lr;
  925.   if (r.lc < oleo_rng->lc)
  926.     r.lc = oleo_rng->lc;
  927.   if (r.hr > oleo_rng->hr)
  928.     r.hr = oleo_rng->hr;
  929.   if (r.hc > oleo_rng->hc)
  930.     r.hc = oleo_rng->hc;
  931.   rname = range_name (&r);
  932.   fprintf (oleo_fp, "%%f %s %s,%s,%f\n",
  933.        rname, font->name, font->psname, font->scale);
  934.   return 1;
  935. }
  936.  
  937.  
  938. #endif
  939.  
  940.